package org.dreamwork.cai.io.impl;

import org.dreamwork.cai.proxy.IServiceResolver;

import java.net.*;

class UdpRouteReceiver implements Runnable {
    private final int localPort;
    private final DatagramPacket packet;
    private final IServiceResolver resolver;

    public UdpRouteReceiver (DatagramPacket packet, int port, IServiceResolver resolver) {
        this.packet    = packet;
        this.localPort = port;
        this.resolver  = resolver;
    }

    @Override
    public void run () {
        if (packet.getLength () > 0) {
            InetSocketAddress address = (InetSocketAddress) packet.getSocketAddress ();
            // 检查是否自己发出的消息
            if (RouteBroadcastProcessor.isLoopBack (address, localPort)) {
                return;
            }

            byte[] buff = packet.getData ();
            int offset = packet.getOffset (), length = packet.getLength ();
            if (offset > 0) {
                byte[] data = new byte[length];
                System.arraycopy (buff, offset, data, 0, length);
                buff = data;
            }
            RouteBroadcastProcessor.handle (buff, offset, length, resolver, address);

/*
            String host = address.getHostString ();
            int port = address.getPort ();
            String key = host + ":" + port;
            if (logger.isTraceEnabled ()) {
                logger.trace ("===============================");
                logger.trace ("= key = {}", key);
                logger.trace ("===============================");

                logger.trace ("receive a message from {}", key);
            }

            if (LOCAL_ADDRESSES.contains (host) && port == localPort) {
                if (logger.isTraceEnabled ()) {
                    logger.trace ("{}:{} is myself, ignore this message!", host, port);
                }

                return;
            }

            byte[] buff = packet.getData ();
            int offset = packet.getOffset (), length = packet.getLength ();
            if (buff.length > 0) {
                String content = new String (buff, offset, length, StandardCharsets.UTF_8);
                Gson g = new Gson ();
                BroadcastPayload payload = g.fromJson (content, BroadcastPayload.class);
                switch (payload.type) {
                    case BroadcastPayload.HEARTBEAT:
                        if (logger.isTraceEnabled ()) {
                            logger.trace ("received heartbeat message from {}", key);
                        }
                        // 更新心跳表时间戳
                        heartbeat.touch (host, port);
                        break;

                    case BroadcastPayload.WITHDRAWN:
                        if (logger.isTraceEnabled ()) {
                            logger.trace ("the SRF of {} withdrawn", key);
                        }
                        // 从本地路由表中删除已取消的路由帧
                        heartbeat.remove (host);
                        table.removeByHost (host, port);
                        break;

                    case BroadcastPayload.UPDATE:
                        if (logger.isTraceEnabled ()) {
                            logger.trace ("the SRF of {} updated", key);
                        }
                        if (payload.srf == null) {
                            logger.warn ("empty srf received, ignore it");
                        } else {
                            try {
                                ServiceRouteFrame cached = table.get (payload.srf.namespace);

                                if (cached != null) {                                   // 如果 srf 曾经缓存过
                                    if (cached.host.equals (host)) {                    // 同个节点发送来的 srf
                                        if (cached.timestamp < payload.srf.timestamp) { // 且远程已更新该 srf
                                            table.remove (cached);                      // 删除老的 srf
                                        }
                                    }
                                }

                                if (cached == null || cached.timestamp < payload.srf.timestamp) {
                                    // 用实际接收的 IP 地址替换 srf 中报告的 host
                                    payload.srf.host = host;
                                    table.add (payload.srf);
                                }
                            } catch (SRFException ex) {
                                logger.warn (ex.getMessage (), ex);
                            }
                        }
                        break;
                }
            }
*/
        }
    }
}

